package com.example.rpc_core.protocal;

import com.example.rpc_core.constance.ProtocolConstant;
import com.example.rpc_core.model.RpcRequestExample;
import com.example.rpc_core.model.RpcResponseExample;
import com.example.rpc_core.serializable.Serializable;
import com.example.rpc_core.serializable.SerializableFactory;
import io.vertx.core.buffer.Buffer;

import java.io.IOException;

/**
 * 协议消息解码器
 */
public class ProtocolMessageDecoder {
    public static ProtocolMessage<?>decode(Buffer buffer) throws IOException {
        ProtocolMessage.Header header=new ProtocolMessage.Header();
        byte magic=buffer.getByte(0);

        if(magic!= ProtocolConstant.PROTOCOL_MAGIC){
            throw new RuntimeException("协议得魔数出现问题");
        }

        header.setMagic(magic);
        header.setVersion(buffer.getByte(1));
        header.setSerializable(buffer.getByte(2));
        header.setType(buffer.getByte(3));
        header.setStatus(buffer.getByte(4));
        header.setRequestId(buffer.getInt(5));
        header.setBodyLength(buffer.getInt(13));

        byte[] bytes = buffer.getBytes(17, 17 + header.getBodyLength());

        ProtocolMessageSerializableEnum enumByKey = ProtocolMessageSerializableEnum.getEnumByKey(header.getSerializable());

        if (enumByKey==null){
            throw new RuntimeException("序列化消息的序列协议");
        }
        Serializable serializable = SerializableFactory.getSerializable(enumByKey.getValue());
        ProtocolMessageTypeEnum  TypeEnum = ProtocolMessageTypeEnum.getProtocolMessageTypeEnum(header.getType());
        if (TypeEnum==null){
            throw new RuntimeException("序列化消息的消息类型不存在");
        }
        switch (TypeEnum){
            case REQUEST:
                RpcRequestExample rpcRequestExample= serializable.deserialize(bytes,RpcRequestExample.class);
                return new ProtocolMessage<>(header,rpcRequestExample);
            case RESPONSE:
                RpcResponseExample rpcResponseExample= serializable.deserialize(bytes, RpcResponseExample.class);
                return new ProtocolMessage<>(header,rpcResponseExample);
            case HEARTBEAT:
            case OTHERS:
            default:
                throw new RuntimeException("未知的消息类型");
        }

    }
}
